Skip to content

feat(workhub): add typed action gate - #3818

Open
ARE404 wants to merge 8 commits into
apache:mainfrom
ARE404:feat/workhub-action-gate
Open

feat(workhub): add typed action gate#3818
ARE404 wants to merge 8 commits into
apache:mainfrom
ARE404:feat/workhub-action-gate

Conversation

@ARE404

@ARE404 ARE404 commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements Slice 4 from #3492 on top of the merged Slice 3 coordination-session work:

  • adds closed typed contracts for answer_here, delegate_existing, create_new, and clarify;
  • exposes a bounded Runtime-owned candidate set with opaque candidate references;
  • introduces a deterministic Runtime Host Action Gate for fresh target validation and execution admission;
  • makes create_new the only WorkHub disposition that can create an ordinary Session;
  • delegates non-destructive create and submit effects through existing Runtime Host Session authorities;
  • routes the production Desktop WorkHub path through the Action Gate while retaining R2.4 only as an explicit regression-test harness.

Safety and authority boundaries

  • Strategy output cannot name arbitrary Session IDs, workspaces, tools, or permission modes.
  • Candidate discovery is scoped to the current Runtime Host and excludes archived, Coordination, side-conversation, and child Sessions.
  • The Gate refreshes candidates before admission and rejects stale or invented references, waiting targets, self-routing, invalid creation context, and conflicting action replays.
  • New ordinary Session identity is derived inside Runtime Host from the action identity; Desktop supplies only trusted workspace context.
  • Successful actions are idempotently replayable; rejected admissions release the action identity so an actionable precondition can be fixed and retried.
  • Tool calls and permission elevation remain owned by the target ordinary Session. The closed WorkHub action protocol provides no field that can widen either ceiling.

Slice boundary: destructive correction is deferred to Slice 5

This PR intentionally does not expose replace or Stop through the Slice 4 Action Gate.

A destructive correction is not just another routing disposition: it must prove durable linkage between the original delegation, the exact root Turn that WorkHub owns, the correcting action, and the replacement submission. That linkage and the recovery contract around the non-atomic Stop-to-submit seam must survive Runtime Host restart. Those are Slice 5 responsibilities in #3492.

Keeping only Host-lifetime ownership maps, TTLs, or retry lanes in Slice 4 would make the behavior appear safe while losing its authorization and recovery basis after restart. The chosen boundary is therefore:

  • Slice 4 owns the typed gate, bounded candidates, fresh validation, action replay, and non-destructive answer_here, clarify, delegate_existing, and create_new effects.
  • Slice 5 will add persistent delegation/action linkage first, then natural-language correction and exact Stop ownership on top of that durable authority.

The protocol decoder is closed and rejects a replace field. The production Action Gate has no Stop effect. Desktop does not offer a correction control; if the routing policy recognizes a natural-language cross-Session correction, production fails closed before a second delegation and tells the user to open the original Session to stop the current work. The legacy R2.4 correction path remains test-only and is not used by the application.

Verification

  • Slice 4 focused Runtime Host suites: 22 passed (including 7 Action Gate tests)
  • Desktop WorkHub suites: 84 passed
  • Desktop production renderer build passed
  • Biome check, format check, and git diff --check passed for all affected files
  • Full all-workspace run was also exercised outside the sandbox: all WorkHub and Desktop tests passed; unrelated workspaces still exposed existing timing-sensitive process tests and an Eval Python-version mismatch

Closes the Slice 4 implementation items in #3492. Persistent delegation linkage, natural-language correction, and Stop/cancel behavior remain Slice 5.

AI assistance: Codex helped implement and verify this change. The commits include the required Generated-by: Codex trailer.

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update on b65c5c2313:

CODE NO-GO — 4×P2

  • P2-1 correction without explicit intent fails confirmation_required before Stop.
  • P2-2 dropping replace when source outside bounded set silently forks while reporting corrected.
  • P2-3 concurrent replacements lack source lock → fan-out to different targets after Stop.
  • P2-4 record 48 KiB vs retry probe 32 KiB → retry after success hits commit_outcome_unknown.

Fix: make correction carry explicit stop text or relax gate; keep replace mandatory or fail; add source lease across actions; align byte limits. Hosted test: SUCCESS does not waive these.

简体中文四处权限/一致性阻塞。

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update on 48666a0ceb:

CODE NO-GO — 3×P2

  • P2 candidate path does not write admitted.targetTurnId to local map → natural-language correction cannot send replacement (fail-closed at 814). E2E workhub-reconstruction fails (32879372758).
  • P2 Stop-then-submit with swallowed replay leaves source stopped and target unconfirmed → retry gets stop_not_owned.
  • P2 48 KiB user + 8 KiB assistant JSON record can exceed 72 KiB retry lookup after escaping → retry becomes commit_outcome_unknown.
简体中文存在路径阻塞与重放问题。

Preserve Runtime-admitted root receipts for natural-language corrections and avoid deleting newer ownership after a concurrent Stop.\n\nGenerated-by: Codex

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update on f2785c5dc0:

CODE NO-GO — 2×P2 plus required check red

  • P2 Stop-then-submit with swallowed replay leaves source stopped and target unconfirmed → retry stop_not_owned.
  • P2 JSON record escaped bytes exceed 72 KiB retry lookup → retry commit_outcome_unknown.

Note: natural-language correction P2 from prior head is now closed (gated receipt saved). Hosted test: FAILURE on format check (new test ternary).

简体中文仍有两处阻塞,另需格式化修复。

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update on 05d3d26e20:

CODE NO-GO — 2×P2 (carry-over, formatting fix only)

  • P2 Stop-then-submit without replay on target failure → retry stop_not_owned.
  • P2 JSON escaped record may exceed 72 KiB retry lookup → commit_outcome_unknown.

Formatting failure from prior head fixed; logic unchanged. Hosted test: QUEUED — not green.

简体中文仍有两处阻塞。

Resume the exact target submission after a replacement Stop and budget summary replay reads for worst-case JSON escaping.\n\nGenerated-by: Codex

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update on 92d0947890:

[P2] #replacementRecoveries can exhaust to Host-wide outage

Capacity 256 is only released on Stop failure or target success. After Stop succeeds, permanent target rejections (e.g. session_busy) keep the recovery forever with no TTL/reaper — 256 failures exhaust replacements Host-wide as host_not_ready until restart.

Fix: give recoveries reconciled lifecycle / TTL for permanent failures.

Checks on 92d0947890d2aeec9a6363f17b68ff0850deb5b0 are test: SUCCESS — code is NO-GO.

简体中文异常恢复容量会耗尽。

Release recovery checkpoints after definitive target failures and expire uncertain outcomes after a bounded reconciliation window.\n\nGenerated-by: Codex

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed this head and found no blocking issues.

Fixes replacement recovery lifecycle (typed failure releases checkpoint, unknown retains fingerprint with 5-min TTL) — closes prior 256-capacity outage; definitive/unknown regression tests pass. Hosted test: SUCCESS (32924223915).

No new P0-P3.

简体中文该头无新增阻断。

Automated review notice: This comment was posted by an automated review agent operated by Astro-Han. It is not an independent human review and does not replace one.

@ARE404
ARE404 force-pushed the feat/workhub-action-gate branch from 3beac53 to 9532d2d Compare August 26, 2026 03:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants